#include <bits/stdc++.h>
// THU20151C. CSV 数据处理
using namespace std;

// 去除前后空格
string trim(const string &s)
{
    size_t start = s.find_first_not_of(" ");
    if (start == string::npos)
        return "";

    size_t end = s.find_last_not_of(" ");
    return s.substr(start, end - start + 1);
}

vector<string> split(const string &s, char delimiter)
{
    vector<string> tokens;
    stringstream ss(s);
    string token;
    while (getline(ss, token, delimiter))
    {
        tokens.push_back(token);
    }
    return tokens;
}

class Node
{
public:
    int _type; // 0 int, 1 string, 2 Date
    bool isSpecial;

    union content
    {
        int num;
        string s;
        tuple<int, int, int> date;
        content() {}
        ~content() {}
    } c;
    Node(string &nodeStr)
    {
        string cur;
        if (nodeStr[0] == '\"')
        {
            assert(nodeStr[nodeStr.size() - 1] == '\"');
            cur = nodeStr.substr(1, nodeStr.size() - 2);
            isSpecial = (cur.find(',') != cur.npos ||
                         (!cur.empty() && (cur[0] == ' ' || cur[cur.size() - 1] == ' ')));
        }
        else
        {
            cur = trim(nodeStr);
            isSpecial = false;
        }
        if (cur.find('/') != string::npos)
        {
            // date
            _type = 2;
            vector<string> ymd = split(cur, '/');
            new (&c.date)
                tuple<int, int, int>(
                    stoi(ymd[0]),
                    stoi(ymd[1]),
                    stoi(ymd[2]));
            return;
        }
        else if (!cur.empty() && (isdigit(cur[0]) || (cur[0] == '-' && cur.length() > 1)) && all_of(cur.begin() + 1, cur.end(), ::isdigit))
        {
            _type = 0;
            c.num = stoi(cur);
        }
        else
        {
            _type = 1;
            new (&c.s) string(cur);
        }
    }
    ~Node()
    {
    }

    Node(const Node &other) : _type(other._type), isSpecial(other.isSpecial)
    {
        switch (_type)
        {
        case 0:
            c.num = other.c.num;
            break;
        case 1:
            new (&c.s) string(other.c.s);
            break;
        case 2:
            new (&c.date) tuple<int, int, int>(other.c.date);
            break;
        }
    }
    Node &operator=(const Node &other)
    {
        if (this == &other)
        {
            return *this;
        }
        // 先销毁当前对象的资源
        this->~Node();
        // 再用拷贝构造的逻辑来复制
        _type = other._type;
        isSpecial = other.isSpecial;
        switch (_type)
        {
        case 0:
            c.num = other.c.num;
            break;
        case 1:
            new (&c.s) string(other.c.s);
            break;
        case 2:
            new (&c.date) tuple<int, int, int>(other.c.date);
            break;
        }
        return *this;
    }

    bool operator>(const Node &other)
    {
        if (_type != other._type)
            return false;
        if (this == &other)
        {
            return false;
        }
        switch (_type)
        {
        case 0:
            return this->c.num > other.c.num;
        case 1:
            return this->c.s > other.c.s;
        case 2:
            return this->c.date > other.c.date;
        default:
            assert(false);
            break;
        }
        return false;
    }
    bool operator<=(const Node &other)
    {
        if (_type != other._type)
            return false;
        return !this->operator>(other);
    }
    bool operator<(const Node &other)
    {
        if (this == &other)
        {
            return false;
        }
        if (_type != other._type)
            return false;
        switch (_type)
        {
        case 0:
            return this->c.num < other.c.num;
        case 1:
            return this->c.s < other.c.s;
        case 2:
            return this->c.date < other.c.date;
        default:
            assert(false);
            break;
        }
        return false;
    }
    bool operator>=(const Node &other)
    {
        if (_type != other._type)
            return false;
        return !this->operator<(other);
    }
    bool operator==(const Node &other)
    {
        if (this == &other)
        {
            return true;
        }
        if (this->_type != other._type)
            return false;
        switch (_type)
        {
        case 0:
            return this->c.num == other.c.num;
        case 1:
            return this->c.s == other.c.s;
        case 2:
            return this->c.date == other.c.date;
        default:
            assert(false);
            break;
        }
        return false;
    }
};

unordered_map<string, int> nameToIndex;
vector<vector<Node>> nodes;
vector<int> sortedIdx;
vector<string> names;
int main()
{
    int n, m;
    cin >> n >> m;
    getchar(); // '\n'
    string line;
    getline(cin, line);
    names = split(line, ',');
    nodes.resize(names.size());
    for (int i = 0; i < names.size(); ++i)
    {
        names[i] = trim(names[i]);
        nameToIndex[names[i]] = i;
    }
    for (int i = 0; i < n - 1; ++i)
    {
        string line;
        getline(cin, line);
        vector<string> tokens;
        string current_token;

        bool in_quotes = false;
        for (char c : line)
        {
            if (c == '\"')
            {
                in_quotes = !in_quotes;
                current_token += c;
            }
            else if (c == ',' && !in_quotes)
            {
                tokens.push_back(current_token);
                current_token.clear();
            }
            else
            {
                current_token += c;
            }
        }
        tokens.push_back(current_token);

        sortedIdx.push_back(i);
        for (int curIdx = 0; curIdx < names.size(); ++curIdx)
        {
            string token = trim(tokens[curIdx]);
            nodes[curIdx].push_back(Node(token));
        }
    }

    for (int i = 0; i < m; ++i)
    {
        string od, name;
        cin >> od >> name;
        vector<Node> &curLine = nodes[nameToIndex[name]];
        if (od == "SORT")
        {
            for (size_t ii = 0; ii < sortedIdx.size(); ++ii)
            {
                for (size_t j = 0; j < sortedIdx.size() - ii - 1; ++j)
                {
                    if ((curLine[sortedIdx[j + 1]]) < (curLine[sortedIdx[j]]))
                    {
                        swap(sortedIdx[j], sortedIdx[j + 1]);
                    }
                }
            }
        }
        else if (od == "FILTER")
        {
            vector<int> newIdx;
            string op, value;
            cin >> op;
            getline(cin, value);
            value = trim(value);
            Node vNode(value);
            for (int idx : sortedIdx)
            {
                Node &cNode = curLine[idx];
                assert(cNode._type == vNode._type);
                bool keep = false;
                if (op == ">")
                    keep = cNode > vNode;
                else if (op == "<")
                    keep = cNode < vNode;
                else if (op == ">=")
                    keep = cNode >= vNode;
                else if (op == "<=")
                    keep = cNode <= vNode;
                else if (op == "=")
                    keep = cNode == vNode;

                if (keep)
                    newIdx.push_back(idx);
            }
            sortedIdx = newIdx;
        }
        else
        {
            assert(false);
        }
    }
    for (int i = 0; i < names.size(); ++i)
    {
        string name = names[i];
        cout << name;
        if (i != names.size() - 1)
        {
            cout << ',';
        }
    }
    cout << '\n';
    for (int idx : sortedIdx)
    {
        int i = 0;
        for (string &name : names)
        {
            Node &cNode = nodes[nameToIndex[name]][idx];
            if (cNode._type == 0)
            {
                cout << cNode.c.num;
            }
            else if (cNode._type == 1)
            {
                if (cNode.isSpecial)
                    cout << '\"';
                cout << cNode.c.s;
                if (cNode.isSpecial)
                    cout << '\"';
            }
            else if (cNode._type == 2)
            {
                int y = get<0>(cNode.c.date),
                    m = get<1>(cNode.c.date),
                    d = get<2>(cNode.c.date);
                cout << y << '/';
                if (m < 10)
                {
                    cout << 0;
                }
                cout << m << '/';
                if (d < 10)
                {
                    cout << 0;
                }
                cout << d;
            }
            else
            {
                // assert(false);
            }
            if (++i != names.size())
            {
                cout << ',';
            }
        }
        cout << endl;
    }

    // system("pause");
    return 0;
}
